home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / SATAN11.ZIP / SRC / MISC / REX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-07  |  6.2 KB  |  270 lines

  1.  /*
  2.   * rex - simplified rexd client. Usage: rex [-a authinfo] server command...
  3.   * 
  4.   * Author: Wietse Venema
  5.   */
  6.  
  7. /* System libraries. */
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <sys/time.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <netdb.h>
  16. #include <memory.h>
  17. #include <string.h>
  18.  
  19.  /*
  20.   * Sun now wants us to #define PORTMAP or things fall apart.
  21.   */
  22. #define PORTMAP
  23. #include <rpc/rpc.h>
  24.  
  25. extern int optind;
  26. extern char *optarg;
  27.  
  28.  /*
  29.   * Many <rpc/rex.h> versions depend on the historical sgttyb
  30.   * terminal control structure. We must use our on version.
  31.   */
  32.  
  33. #include "rex.h"
  34.  
  35. /* Local stuff. */
  36.  
  37. static char *progname;
  38. static CLIENT *rex_server();
  39. static AUTH *rex_auth();
  40. static int rex_command();
  41. static void rex_startup();
  42. static void do_io();
  43. static int rex_exit();
  44. static int stream_port();
  45.  
  46. /* Defaults. */
  47.  
  48. static struct timeval timeout = {10, 0};
  49.  
  50. static char *serv_env[] = {
  51.     "PATH=/usr/ucb:/bin:/usr/bin",
  52.     0,
  53. };
  54.  
  55. static void usage()
  56. {
  57.     printf("Usage: %s [-a authinfo] server command...\n", progname);
  58.     exit(1);
  59. }
  60.  
  61. main(argc, argv)
  62. int     argc;
  63. char  **argv;
  64. {
  65.     int     c;
  66.     CLIENT *client;
  67.     int     server_sock;
  68.     char   *auth = 0;
  69.  
  70.     progname = argv[0];
  71.  
  72.     while ((c = getopt(argc, argv, "a:")) != EOF) {
  73.     switch (c) {
  74.     case 'a':
  75.         auth = optarg;
  76.         break;
  77.     default:
  78.         usage();
  79.     }
  80.     }
  81.     argc -= optind;
  82.     argv += optind;
  83.     if (argc < 2)
  84.     usage();
  85.  
  86.     /* Establish rexd server, run command, and clean up. */
  87.  
  88.     client = rex_server(argv[0]);
  89.     client->cl_auth = (auth == 0) ? authunix_create_default() : rex_auth(auth);
  90.     server_sock = rex_command(client, argv[0], argv + 1);
  91.     do_io(server_sock);
  92.     return (rex_exit(client, server_sock));
  93. }
  94.  
  95. /* rex_server - establish rexd server instance */
  96.  
  97. static CLIENT *rex_server(server_name)
  98. char   *server_name;
  99. {
  100.     struct hostent *hp;
  101.     struct sockaddr_in server_addr;
  102.     int     sock = RPC_ANYSOCK;
  103.     CLIENT *client;
  104.  
  105.     /* Find server's IP address. */
  106.  
  107.     if ((hp = gethostbyname(server_name)) == 0) {
  108.     fprintf(stderr, "%s: host not found\n", server_name);
  109.     exit(1);
  110.     }
  111.     /* XXX should iterate over all IP addresses. */
  112.  
  113.     server_addr.sin_family = AF_INET;
  114.     memcpy((caddr_t) & server_addr.sin_addr, hp->h_addr, hp->h_length);
  115.     server_addr.sin_port = 0;
  116.  
  117.     if ((client = clnttcp_create(&server_addr,
  118.                  REXPROG, REXVERS,
  119.                  &sock, 0, 0)) == 0) {
  120.     fprintf(stderr, "%s: ", server_name);
  121.     clnt_pcreateerror(server_name);
  122.     fprintf(stderr, "\n");
  123.     exit(1);
  124.     }
  125.     return (client);
  126. }
  127.  
  128. /* rex_auth - handle explicit credentials */
  129.  
  130. static AUTH *rex_auth(auth)
  131. char   *auth;
  132. {
  133.     char    host[BUFSIZ];
  134.     int     uid;
  135.     AUTH_GID_T gid;
  136.  
  137.     if (sscanf(auth, "%[^,],%d,%d", host, &uid, &gid) != 3)
  138.     usage();
  139.     return (authunix_create(host, uid, gid, 1, &gid));
  140. }
  141.  
  142. /* rex_command - open socket to remote command */
  143.  
  144. static int rex_command(client, server_name, command)
  145. CLIENT *client;
  146. char   *server_name;
  147. char  **command;
  148. {
  149.     static rex_start rx_start;
  150.     static rex_result rx_result;
  151.     enum clnt_stat stat;
  152.     int     sock;
  153.     int     server_sock;
  154.     char    cwd_host[BUFSIZ];
  155.     char  **cpp;
  156.  
  157.     sscanf(server_name, "%[^.]", cwd_host);    /* XXX for old servers */
  158.  
  159.     rx_start.rst_cmd.rst_cmd_val = command;
  160.     for (cpp = command; *cpp; cpp++)
  161.      /* void */ ;
  162.     rx_start.rst_cmd.rst_cmd_len = cpp - command;
  163.     rx_start.rst_host = cwd_host;        /* cwd server */
  164.     rx_start.rst_fsname = "";            /* cwd file system */
  165.     rx_start.rst_dirwithin = "";        /* cwd offset */
  166.     rx_start.rst_env.rst_env_val = serv_env;
  167.     for (cpp = serv_env; *cpp; cpp++)
  168.      /* void */ ;
  169.     rx_start.rst_env.rst_env_len = cpp - serv_env;
  170.     rx_start.rst_port0 = stream_port(&sock);
  171.     rx_start.rst_port1 = rx_start.rst_port0;
  172.     rx_start.rst_port2 = rx_start.rst_port1;
  173.     rx_start.rst_flags = 0;
  174.  
  175.     if (stat = clnt_call(client, REXPROC_START,
  176.              xdr_rex_start, (void *) &rx_start,
  177.              xdr_rex_result, (void *) &rx_result,
  178.              timeout)) {
  179.     fprintf(stderr, "%s: ", progname);
  180.     clnt_perrno(stat);
  181.     fprintf(stderr, "\n");
  182.     exit(1);
  183.     }
  184.     if (rx_result.rlt_stat) {
  185.     fprintf(stderr, "%s: %s\n", progname, rx_result.rlt_message);
  186.     exit(1);
  187.     }
  188.     if ((server_sock = accept(sock, (struct sockaddr *) 0, (int *) 0)) < 0) {
  189.     perror("accept");
  190.     exit(1);
  191.     }
  192.     close(sock);
  193.     return (server_sock);
  194. }
  195.  
  196. /* do_io - shuffle bits across the network */
  197.  
  198. static void do_io(sock)
  199. int     sock;
  200. {
  201.     char    buf[BUFSIZ];
  202.     int     count;
  203.  
  204.     shutdown(sock, 1);                /* make server read EOF */
  205.     while ((count = read(sock, buf, sizeof(buf))) > 0)
  206.     write(1, buf, count);
  207. }
  208.  
  209. /* rex_exit - terminate remote command and get its exit status */
  210.  
  211. static int rex_exit(client, server_sock)
  212. CLIENT *client;
  213. int     server_sock;
  214. {
  215.     static struct rex_result rx_result;
  216.     enum clnt_stat stat;
  217.  
  218.     close(server_sock);
  219.     if (stat = clnt_call(client, REXPROC_WAIT,
  220.              xdr_void, (void *) 0,
  221.              xdr_rex_result, (void *) &rx_result,
  222.              timeout)) {
  223.     fprintf(stderr, "%s ", progname);
  224.     clnt_perrno(stat);
  225.     fprintf(stderr, "\n");
  226.     exit(1);
  227.     }
  228.     return (rx_result.rlt_stat);
  229. }
  230.  
  231. /* stream_port - create ready-to-accept socket and return port number */
  232.  
  233. static int stream_port(sockp)
  234. int    *sockp;
  235. {
  236.     struct sockaddr_in sin;
  237.     int     sock;
  238.     int     len;
  239.  
  240.     /* Create socket. */
  241.  
  242.     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  243.     perror("socket");
  244.     exit(1);
  245.     }
  246.     /* Bind the socket to some random port. */
  247.  
  248.     memset((char *) &sin, 0, sizeof(sin));
  249.     sin.sin_family = AF_INET;
  250.     if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
  251.     perror("bind");
  252.     exit(1);
  253.     }
  254.     /* Find out the socket's port number. */
  255.  
  256.     len = sizeof(sin);
  257.     if (getsockname(sock, (struct sockaddr *) & sin, &len) < 0) {
  258.     perror("getsockname");
  259.     exit(1);
  260.     }
  261.     /* Make the socket ready to receive connections. */
  262.  
  263.     if (listen(sock, 1) < 0) {
  264.     perror("listen");
  265.     exit(1);
  266.     }
  267.     *sockp = sock;
  268.     return (htons(sin.sin_port));
  269. }
  270.